<?php

namespace App\models;

use Core\BeanFactory;
use Core\init\MyDb;
use Illuminate\Database\Eloquent\Model;

class DbModel extends Model
{
    protected $myDb;
    //TODO 调用原来的方法/部分静态方法 会重新生成一个连接并非从连接池获取,且操作完成未将连接池回收
    //TODO 模型内含有的方法必须重写
    //TODO 模型内含有的静态方法部分需要重写,因为部分静态方法  return static::query()->xxx....实际调用的是__callStatic(此处实际调用的是重写的__call), 另外部分非调用则需要重写

    public $timestamps = false;

    /**
     * 无需重写__callStatic 方法,实质上 __callStatic   return (new static)->$method(...$parameters); 调用的是__call方法
     * @param string $name
     * @param array $arguments
     * @return mixed
     * @throws \DI\DependencyException
     * @throws \DI\NotFoundException
     */
    public function __call($name, $arguments)
    {
        return $this->invoke(function () use ($name, $arguments) {
            return parent::__call($name, $arguments);
        });
    }

    /**
     * 重写save 方法
     * @param array $options
     * @return bool|mixed
     * @throws \DI\DependencyException
     * @throws \DI\NotFoundException
     */
    public function save(array $options = [])
    {
        return $this->invoke(function () use ($options) {
            return parent::save($options);
        });
    }

    /**
     * 重写静态方法all
     * @param array $columns
     * @return \Illuminate\Database\Eloquent\Collection|Model[]|mixed
     * @throws \DI\DependencyException
     * @throws \DI\NotFoundException
     */
    public static function all($columns = ['*'])
    {
        return self::invoke(function () use ($columns) {
            return parent::all($columns);
        });
    }

    /**
     * 通过回调函数 调用ORM相关方法
     * @param callable $func [回调函数调用原来的方法]
     * @return mixed
     * @throws \DI\DependencyException
     * @throws \DI\NotFoundException
     */
    protected function invoke(callable $func)
    {
        //调用静态方法的时候 调用MyDb类 生成 PdoConnect
        $myDb = clone BeanFactory::getBean(MyDb::class);
        /**@var $myDb MyDb* */
        //获取连接
        $obj = $myDb->genConnect();
        try {
            return $func();
        } catch (\Exception $exception) {
            var_dump($exception);
            throw $exception;
        } finally {
            //回收连接
            $myDb->releaseConnect($obj);
        }
    }

    public function setDB($db = false)
    {
        $this->myDb = $db;
    }
}
